<template>
  <q-layout>
    <q-page-container>
      <q-page class="q-pa-md">
        <q-form ref="articleForm">
          <div class="row">
            <div class="col-5">
              <div class="q-mr-sm">
                <q-input
                  bottom-slots
                  v-model="formBody.title"
                  label="标题 *"
                  counter
                  dense
                  type="textarea"
                  clearable
                  maxlength="100"
                  :rules="[(val) => (val && val.length > 0) || '请输入文章标题']"
                >
                </q-input>
              </div>
            </div>
            <div class="col-7">
              <div>
                <q-input
                  bottom-slots
                  v-model="formBody.summary"
                  label="摘要 *"
                  counter
                  dense
                  type="textarea"
                  clearable
                  maxlength="210"
                  :rules="[(val) => (val && val.length > 0) || '请输入文章摘要']"
                >
                </q-input>
              </div>
            </div>
          </div>
          <div class="row q-py-sm">
            <div class="col-7 row q-gutter-sm">
              <q-btn
                :class="
                  formBody.categoryId == item.value
                    ? $q.dark.isActive
                      ? 'bg-gray-6'
                      : 'bg-light-blue-2'
                    : ''
                "
                v-for="item in pageInit.categoryList"
                :key="item.value"
                :label="item.label"
                @click="
                  () => {
                    formBody.categoryId = item.value
                  }
                "
              />
            </div>
          </div>
          <div class="row q-py-sm">
            <div class="col-7">
              <div class="q-mr-sm">
                <q-select
                  label="选择或输入文章标签"
                  new-value-mode="add-unique"
                  dense
                  multiple
                  use-input
                  use-chips
                  input-debounce="0"
                  @new-value="createValue"
                  @filter="filterTagFn"
                  v-model="formBody.tagList"
                  :options="tagOptions"
                  :rules="[
                    (val) =>
                      (val && val.length > 0 && val.length < 4) || '至少选择一个标签,不可超过三个',
                  ]"
                  popup-content-class="w-340px max-h-xs"
                >
                  <template v-slot:selected-item="scope">
                    <q-chip
                      removable
                      dense
                      square
                      @remove="scope.removeAtIndex(scope.index)"
                      :tabindex="scope.tabindex"
                      :color="$q.dark.isActive ? 'grey-8' : 'blue-2'"
                      class="q-mx-xs"
                    >
                      {{ scope.opt.label }}
                    </q-chip>
                  </template>

                  <template v-slot:option="scope">
                    <q-item v-bind="scope.itemProps">
                      <q-item-section>
                        <q-item-label>{{ scope.opt.label }}</q-item-label>
                      </q-item-section>
                    </q-item>
                  </template>
                </q-select>
              </div>
            </div>
            <div class="col-5">
              <q-select
                label="选择文章附带话题"
                dense
                use-input
                use-chips
                popup-content-class="max-h-xs"
                @filter="filterTopicFn"
                v-model="formBody.topic"
                :options="topicOptions"
                :rules="[(val) => val || '选择一个话题']"
              >
                <template v-slot:selected-item="scope">
                  <q-chip
                    removable
                    dense
                    square
                    @remove="scope.removeAtIndex(scope.index)"
                    :tabindex="scope.tabindex"
                    :color="$q.dark.isActive ? 'grey-8' : 'blue-2'"
                    class="q-mx-xs"
                  >
                    #{{ scope.opt.label }}#
                  </q-chip>
                </template>

                <template v-slot:option="scope">
                  <q-item v-bind="scope.itemProps">
                    <q-item-section>
                      <q-item-label>#{{ scope.opt.label }}#</q-item-label>
                    </q-item-section>
                  </q-item>
                </template>
              </q-select>
            </div>
          </div>

          <div class="row items-center">
            <div class="row">
              <q-file
                @rejected="rejected"
                :max-file-size="1024 * 5 * 1000"
                dense
                accept=".jpg,.pdf,image/*"
                display-value="上传封面"
                v-model="formImg"
              >
                <template v-slot:prepend>
                  <q-icon name="cloud_upload" @click.stop />
                </template>
              </q-file>
            </div>
            <div class="col">
              <div class="q-ml-sm">
                <q-input
                  v-model="formBody.articleCover"
                  label="封面,可直接输入图片链接或点击右侧输入框上传图片"
                  dense
                >
                  <template v-slot:append>
                    <q-icon
                      name="close"
                      @click.stop="
                        () => {
                          delImg()
                          formBody.articleCover = ''
                        }
                      "
                      class="cursor-pointer"
                    />
                  </template>
                </q-input>
              </div>
            </div>
            <div class="q-ml-md" v-if="formBody.articleCover">
              <q-img :src="formBody.articleCover" loading="lazy" width="300px" height="200px" />
            </div>
            <div
              v-else
              style="width: 300px; height: 200px"
              class="q-ml-md flex flex-center items-center bg-neutral-100 dark:bg-neutral-800 rounded-borders"
            >
              封面预览
            </div>
          </div>
        </q-form>

        <div class="q-pt-md">
          <MdEditor
            style="height: 80vh"
            :placeholder="'腹有诗书气自华...'"
            :footers="footers"
            :theme="$q.dark.isActive ? 'dark' : 'light'"
            v-model="formBody.content"
            @onUploadImg="onUploadImg"
            editorId="publishArticleEditor"
            @on-change="
              () => {
                onChange()
              }
            "
            @on-html-changed="
              (h) => {
                formBody.htmlContent = h
              }
            "
            @on-save="
              () => {
                onSave()
              }
            "
          >
            <template #defFooters>
              <span></span>
              <span><TimeNow></TimeNow></span>
            </template>
          </MdEditor>
        </div>

        <div class="q-pt-sm row justify-center q-gutter-md">
          <div>
            <q-btn
              v-if="artData?.status == 0 || props.id == ''"
              color="positive"
              class="w-20"
              label="发布"
              @click="
                () => {
                  push()
                }
              "
            />
            <q-btn
              v-if="props.id != ''"
              color="primary"
              class="q-ml-sm w-20"
              label="更新"
              @click="
                () => {
                  edit()
                }
              "
            />
            <q-btn
              v-if="props.id == ''"
              color="warning"
              class="q-ml-sm w-30"
              label="保存草稿"
              @click="
                () => {
                  toDraft()
                }
              "
            />
          </div>
          <div v-if="artData">
            文章状态:
            <q-chip v-if="artData?.status == 1" color="positive" square label="已发布" />
            <q-chip v-else color="warning" square label="草稿" />
          </div>
          <div v-if="artData">
            最后保存时间：
            <q-chip square :label="artData?.updateTime" />
          </div>
        </div>
        <q-page-sticky position="top-right" :offset="[18, 18]" expand>
          <q-btn color="primary" to="/" icon="home" round>
            <q-tooltip> 回到首页 </q-tooltip>
          </q-btn>
        </q-page-sticky>
      </q-page>
    </q-page-container>
  </q-layout>
</template>

<script setup lang="ts">
import TimeNow from './TimeNow.vue'
import { onMounted, ref, watch } from 'vue'
import { MdEditor } from 'md-editor-v3'
import 'md-editor-v3/lib/style.css'
import { articleOperateEditData, articleOperateInit, globalUploadImg } from 'src/service/api'
import { useYuan } from 'src/use'
import { formBody, artData, pageInit } from './shared'
import type { QSelectProps, QRejectedEntry } from 'quasar'
import { QForm, useQuasar } from 'quasar'
import { useRouter } from 'vue-router'
import {
  articleOperateEdit,
  articleOperatePush,
  articleOperateToDraft,
  globalDelImg,
} from 'src/service/api'

defineOptions({
  name: 'addBlog',
})

const $q = useQuasar()

const footers: Array<'=' | 'markdownTotal' | 'scrollSwitch' | number> = [
  'markdownTotal',
  0,
  '=',
  1,
  'scrollSwitch',
]

const props = withDefaults(
  defineProps<{
    id?: string
  }>(),
  {
    id: '',
  },
)

const onChange = () => {}

const onSave = () => {
  if (props.id) {
    edit()
  } else {
    toDraft()
  }
}

const { Ok, Warn, Confirm } = useYuan()

/* 博客中上传图片 */
const onUploadImg = async (files: Array<File>, callback: (urls: Array<string>) => void) => {
  files.map((file) => {
    const formData = new FormData()
    formData.append('file', file)
    if (file.size > 1024 * 5 * 1000) {
      Warn('图片最大尺寸5MB, 请不要选择过大的图片')
      return
    }
    globalUploadImg(formData).then(({ data, error }) => {
      if (error) {
        return
      }
      Ok('上传成功')
      callback([data.url])
    })
  })
}

const init = () => {
  articleOperateInit().then(({ data }) => {
    if (data) {
      pageInit.value = data
      if (pageInit.value.categoryList[0]) {
        formBody.value.categoryId = pageInit.value.categoryList[0].value
        artInit()
      }
    }
  })
}

const artInit = () => {
  if (props.id) {
    articleOperateEditData({ id: props.id }).then(({ data }) => {
      if (data) {
        Object.assign(formBody.value, data)
        artData.value = data
      }
    })
  }
}

onMounted(() => {
  init()
})

const { replace } = useRouter()

const articleForm = ref<QForm>()

const formImg = ref<File>()

/* 监听上传图片 */
watch(formImg, (newVal) => {
  if (newVal) {
    const formData = new FormData()
    formData.append('file', formImg.value as File)
    globalUploadImg(formData).then(({ error, data }) => {
      if (error) {
        return
      }
      Ok('上传封面成功')
      formBody.value.articleCover = data.url
      formImg.value = undefined
    })
  }
})

const delImg = () => {
  if (formBody.value.articleCover) {
    globalDelImg({ href: formBody.value.articleCover }).then(({ error }) => {
      if (error) {
        return
      }
      Ok('删除图片成功')
      formBody.value.articleCover = ''
    })
  }
}

const tagOptions = ref(pageInit.value.tagList)
const topicOptions = ref(pageInit.value.topicList)

type onNewValueParam = Parameters<NonNullable<QSelectProps['onNewValue']>>

const createValue = (val: onNewValueParam[0], done: onNewValueParam[1]) => {
  const tabList = pageInit.value.tagList.filter((i) => i.label == val)
  if (tabList.length > 0) {
    if (tabList[0]) {
      done({ label: tabList[0].label, value: tabList[0].value }, 'add-unique')
    }
  } else {
    done({ label: val, value: 'new-val' }, 'add-unique')
  }
}

type onFilterParam = Parameters<NonNullable<QSelectProps['onFilter']>>

const filterTagFn = (val: onFilterParam[0], update: onFilterParam[1]) => {
  update(() => {
    if (val === '') {
      tagOptions.value = pageInit.value.tagList
    } else {
      const needle = val.toLowerCase()
      tagOptions.value = pageInit.value.tagList
        .slice()
        .filter((v) => v.label.toLowerCase().indexOf(needle) > -1)
    }
  })
}

const filterTopicFn = (val: onFilterParam[0], update: onFilterParam[1]) => {
  update(() => {
    if (val === '') {
      topicOptions.value = pageInit.value.topicList
    } else {
      const needle = val.toLowerCase()
      topicOptions.value = pageInit.value.topicList
        .slice()
        .filter((v) => v.label.toLowerCase().indexOf(needle) > -1)
    }
  })
}

/* 图片校验 */
const rejected = (err: QRejectedEntry[]) => {
  err.forEach((err) => {
    if (err.failedPropValidation == 'max-file-size') {
      Warn('图片最大尺寸5MB, 请不要选择过大的图片')
    }
  })
}

/* 保存至草稿 */
const toDraft = () => {
  articleForm.value?.validate().then((success) => {
    if (success) {
      articleOperateToDraft(formBody.value).then(({ error, data }) => {
        if (error) {
          return
        }
        Ok('已保存至草稿')
        replace({
          path: '/add-blog',
          query: { id: data },
        }).then(() => {
          artInit()
        })
      })
    } else {
      Warn('请按提示输入必要内容')
    }
  })
}

/* 发布 */
const push = () => {
  articleForm.value?.validate().then((success) => {
    if (success) {
      articleOperatePush(formBody.value).then(({ error }) => {
        if (error) {
          return
        }
        Confirm('发布成功是否跳转到主页?', () => {
          replace({
            path: '/',
          })
        })
      })
    } else {
      Warn('请按提示输入必要内容!')
    }
  })
}

/* 编辑 */
const edit = () => {
  articleForm.value?.validate().then((success) => {
    if (success) {
      if (artData.value) {
        formBody.value.id = artData.value.id
        articleOperateEdit(formBody.value).then(({ error }) => {
          if (error) {
            return
          }
          Ok('编辑成功')
          artInit()
        })
      }
    } else {
      Warn('请按提示输入必要内容!')
    }
  })
}
</script>

<style scoped></style>
